"""
基础爬虫抽象类
"""

from abc import ABC, abstractmethod
from typing import List, Dict, Any
import aiohttp
import asyncio
from ..core.logger import app_logger


class BaseScraper(ABC):
    """爬虫基类"""
    
    def __init__(self):
        self.session = None
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
    
    @property
    @abstractmethod
    def name(self) -> str:
        """爬虫名称"""
        pass
    
    @property
    @abstractmethod
    def description(self) -> str:
        """爬虫描述"""
        pass
    
    @abstractmethod
    async def scrape(self) -> List[Dict[str, Any]]:
        """抓取数据的主要方法"""
        pass
    
    async def get_session(self) -> aiohttp.ClientSession:
        """获取HTTP会话"""
        if not self.session:
            timeout = aiohttp.ClientTimeout(total=30)
            connector = aiohttp.TCPConnector(ssl=False)  # 禁用SSL验证
            self.session = aiohttp.ClientSession(
                headers=self.headers,
                timeout=timeout,
                connector=connector
            )
        return self.session
    
    async def fetch(self, url: str, **kwargs) -> str:
        """发起HTTP请求"""
        session = await self.get_session()
        
        try:
            async with session.get(url, **kwargs) as response:
                if response.status == 200:
                    # 尝试不同的编码方式
                    try:
                        return await response.text()
                    except UnicodeDecodeError:
                        # 如果UTF-8解码失败，尝试其他编码
                        content = await response.read()
                        # 尝试GBK编码
                        try:
                            return content.decode('gbk')
                        except UnicodeDecodeError:
                            # 使用ISO-8859-1编码作为后备
                            return content.decode('iso-8859-1')
                else:
                    app_logger.warning(f"请求失败: {url}, 状态码: {response.status}")
                    return ""
        except Exception as e:
            app_logger.error(f"请求异常: {url}, 错误: {str(e)}")
            return ""
    
    async def close(self):
        """关闭会话"""
        if self.session:
            await self.session.close()
            self.session = None
    
    def __del__(self):
        """析构函数"""
        if self.session:
            asyncio.create_task(self.close())